package com.gxjtkyy.datadistributer.writer.rdbms.util;

import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.gxjtkyy.datadistributer.common.dto.DbRecord;
import com.gxjtkyy.datadistributer.common.dto.XField;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DbRecordUtil {
   private static final Logger logger = LoggerFactory.getLogger(DbRecordUtil.class);
   private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
   private static final Pattern PATTERN = Pattern.compile("INSERT\\s+INTO\\s+([A-Za-z_]+)\\s*\\(([\\s\\S]*)\\)\\s*VALUES\\s*\\(([\\s\\S]*)\\)");

   private DbRecordUtil() {
   }

   public static DbRecord generateDbRecord(String tableName, sqlMaker maker) {
      DbRecord dbRecord = new DbRecord();
      dbRecord.setTable(tableName);
      dbRecord.setAction("update");
      dbRecord.setFields(generateXFields(maker, getKeyColumns(tableName, "")));
      return dbRecord;
   }

   public static DbRecord generateDbRecord(String insertSql) {
      Matcher matcher = PATTERN.matcher(insertSql);
      Preconditions.checkArgument(matcher.matches(), "非标准insertSql=" + insertSql);
      String tableName = matcher.group(1);
      String fieldStr = matcher.group(2);
      String recordStr = matcher.group(3);
      DbRecord dbRecord = new DbRecord();
      dbRecord.setTable(tableName);
      dbRecord.setAction("update");
      dbRecord.setFields(generateXFields(getKeyColumns(tableName, insertSql), fieldStr, recordStr));
      return dbRecord;
   }

   private static Set<String> getKeyColumns(String tableName, String insertSql) {
      Set<String> keyColumns = (Set)GantryTableNameRes.keyColumnsMap.get(tableName.toUpperCase());
      return (Set)Objects.requireNonNull(keyColumns, "主键配置不存在, insertsql=" + insertSql);
   }

   public static List<XField> generateXFields(sqlMaker maker, Set<String> keyColumns) {
      String fieldStr = maker.getFields().toString();
      String recordStr = maker.getRecords().toString();
      return generateXFields(keyColumns, removeBrackets(fieldStr), removeBrackets(recordStr));
   }

   public static String getKafkaKey(DbRecord dbRecord) {
      return (String)dbRecord.getFields().stream().filter(XField::isKey).sorted(Comparator.comparing((xField) -> {
         return xField.getName().toUpperCase();
      })).map((xField) -> {
         return Strings.nullToEmpty(xField.getValue());
      }).collect(Collectors.joining("|"));
   }

   private static String removeBrackets(String s) {
      return s.replaceFirst("^\\s*\\(", "").replaceAll("\\)\\s*$", "");
   }

   private static List<XField> generateXFields(Set<String> keyColumns, String fieldStr, String recordStr) {
      List<String> fields = parseFromParams(fieldStr);
      List<String> records = parseFromParams(recordStr);
      Preconditions.checkArgument(fields.size() == records.size(), "字段和参数数量不一致");
      List<XField> xFields = new ArrayList();

      for(int i = 0; i < fields.size(); ++i) {
         XField xField = new XField();
         xField.setIdx(i + 1);
         String columnName = (String)fields.get(i);
         xField.setName(columnName);
         xField.setKey(keyColumns.contains(columnName));
         String record = (String)records.get(i);
         if (record.matches("\\d+")) {
            xField.setType(25);
            xField.setValue(record);
         } else if (record.matches("\\d+\\.\\d+")) {
            xField.setType(6);
            xField.setValue(record);
         } else if (record.startsWith("'") && record.endsWith("'")) {
            xField.setType(1);
            xField.setValue(record.substring(1, record.length() - 1).replace("''", "'"));
         } else if (record.toUpperCase().startsWith("TO_DATE")) {
            xField.setType(11);
            int index1 = record.indexOf("'");
            int index2 = record.indexOf("'", index1 + 1);
            xField.setValue(record.substring(index1 + 1, index2));
         } else if (record.toUpperCase().startsWith("LOCALTIMESTAMP")) {
            xField.setType(11);
            xField.setValue(FORMATTER.format(LocalDateTime.now()));
         } else if ("null".equalsIgnoreCase(record)) {
            xField.setType(0);
            xField.setValue((String)null);
         } else {
            logger.error("未知数据类型, record=" + record);
            xField.setType(1);
            xField.setValue(record);
         }

         xFields.add(xField);
      }

      return xFields;
   }

   private static List<String> parseFromParams(String params) {
      Splitter splitter = Splitter.on(',').omitEmptyStrings();
      List<String> strings = splitter.splitToList(params);
      if (strings.isEmpty()) {
         return Collections.emptyList();
      } else {
         String tmp = null;
         List<String> result = new ArrayList();
         Iterator var5 = strings.iterator();

         while(var5.hasNext()) {
            String string = (String)var5.next();
            if (tmp == null) {
               tmp = string;
            } else {
               tmp = tmp + "," + string;
            }

            if (isComplete(tmp.trim())) {
               result.add(tmp.trim());
               tmp = null;
            }
         }

         if (tmp != null) {
            result.add(tmp);
         }

         return result;
      }
   }

   private static boolean isComplete(String param) {
      if (!param.contains("'")) {
         return true;
      } else if (param.startsWith("'") && param.endsWith("'")) {
         param = param.substring(1, param.length() - 1).replace("''", "");
         return !param.contains("'");
      } else {
         return param.matches("^[A-Za-z_][A-Za-z0-9_]*\\([^)]*\\)$");
      }
   }
}
